// (C) Copyright to Kevin. Applied to MIT LICENSE

#include "ChunkRenderTask.h"

#include "../BlockWorld.h"
#include "BlockEngineGameMode.h"
#include "Blocks/CubicBlock.h"
#include "ChunkActor.h"
#include "ProceduralMeshComponent/Public/ProceduralMeshComponent.h"

ChunkRenderTask::ChunkRenderTask(FChunkCoordinate coordinate, AChunkActor* source)
{
	this->coordinate = coordinate;
	this->source = source;

	block_manager = ABlockEngineGameMode::GetInstance()->GetBlockManager();
	texture_manager = ABlockEngineGameMode::GetInstance()->GetTextureManager();
}

ChunkRenderTask::~ChunkRenderTask()
{
}

void ChunkRenderTask::Abandon()
{
}

void ChunkRenderTask::DoThreadedWork()
{
	// UE_LOG(BlockEngine, Log, TEXT("Threaded work called! "));

	TArray<FVector>* verticies = new TArray<FVector>();
	TArray<int32>* triangles = new TArray<int32>();
	TArray<FVector2D>* uv0 = new TArray<FVector2D>();
	TArray<FVector2D>* uv1 = new TArray<FVector2D>();
	TArray<FVector2D>* uv2 = new TArray<FVector2D>();
	TArray<FVector2D>* uv_empty = new TArray<FVector2D>();

	TArray<FColor>* empty_color_array = new TArray<FColor>();
	TArray<FVector>* empty_vector_array = new TArray<FVector>();
	TArray<FProcMeshTangent>* empty_tangent_array = new TArray<FProcMeshTangent>();

	// do the real shit
	ChunkData* source_data = source->GetChunkData();
	for (int x = 0; x < 16; x++) {
		for (int y = 0; y < 16; y++) {
			for (int z = 0; z < 16; z++) {
				// we MUST convert to UE format, from XYZ(Y=up) to XZY(Z=up)! 
				int i = BlockIndex(x, y, z);
				uint16 id = source_data->id[i];
				Block * def = block_manager->Find(id);
				if (!def) continue;
				if (def->GetBlockType() == BLOCK_TYPE_CUBIC) {
					CubicBlock* cubic = (CubicBlock*) def;
					cubic->Render(this, x, y, z, verticies, triangles, uv0, uv1, uv2);
				} else {
					// ...
				}
			}
		}
	}


	FFunctionGraphTask::CreateAndDispatchWhenReady([=] {
		UProceduralMeshComponent* component = (UProceduralMeshComponent*)source->GetRootComponent();
		if (component == nullptr) {
			UE_LOG(BlockEngine, Log, TEXT("WTF?? UProceduralMeshComponent is NULL!!!!! "));
			return;
		}

		// Final Refresh
		component->CreateMeshSection(0, *verticies, *triangles, *empty_vector_array, *uv0, *uv1, *uv2, *uv_empty, *empty_color_array, *empty_tangent_array, true);

		delete verticies;
		delete triangles;
		delete uv0;
		delete uv1;
		delete uv2;
		delete uv_empty;
		delete empty_color_array;
		delete empty_vector_array;
		delete empty_tangent_array;

		delete this;

	}, TStatId(), nullptr, ENamedThreads::GameThread);

	// UE_LOG(BlockEngine, Log, TEXT(" -- Thread work finished! "));
}

FChunkCoordinate ChunkRenderTask::GetChunkCoordinate()
{
	return coordinate;
}

AChunkActor * ChunkRenderTask::GetSourceChunk()
{
	return source;
}
